/*
 * CameraManager - 摄像头管理工具类实现
 */
#include "cameraManager.h"
#include <Arduino.h>

// 选择摄像头型号
#define CAMERA_MODEL_ESP32S3_EYE // Has PSRAM
#include "camera_pins.h"

// 构造函数
CameraManager::CameraManager() {
  _status = CAMERA_IDLE;
  _frameCallback = NULL;
  _statusCallback = NULL;
  _captureInterval = 0;
  _lastCaptureTime = 0;
  _isCapturing = false;
}

// 析构函数
CameraManager::~CameraManager() {
  stopCapture();
  esp_camera_deinit();
}

// 初始化摄像头
bool CameraManager::init() {
  _updateStatus(CAMERA_INITIALIZING);
  
  // 摄像头配置
  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sccb_sda = SIOD_GPIO_NUM;
  config.pin_sccb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  // config.xclk_freq_hz = 8000000;
  // config.frame_size = FRAMESIZE_QVGA;
  // 2K 图像的采样频率
  config.xclk_freq_hz = 20000000; // 1080p 通常使用 20MHz 采样率
  config.frame_size = FRAMESIZE_FHD; // FRAMESIZE_FHD 对应 1080p 分辨率
  
  config.pixel_format = PIXFORMAT_JPEG; // 用于流式传输
  config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
  config.fb_location = CAMERA_FB_IN_PSRAM;
  config.jpeg_quality = 12;
  config.fb_count = 1;
  
  // 如果有PSRAM，使用更高的JPEG质量和多个帧缓冲区
  if(config.pixel_format == PIXFORMAT_JPEG){
    if(psramFound()){
      config.jpeg_quality = 10;
      config.fb_count = 2;
      config.grab_mode = CAMERA_GRAB_LATEST;
    } else {
      // 没有PSRAM时限制帧大小
      config.frame_size = FRAMESIZE_SVGA;
      config.fb_location = CAMERA_FB_IN_DRAM;
    }
  } else {
    // 人脸检测/识别的最佳选择
    config.frame_size = FRAMESIZE_240X240;
#if CONFIG_IDF_TARGET_ESP32S3
    config.fb_count = 2;
#endif
  }
  
  // 摄像头初始化
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x\n", err);
    _updateStatus(CAMERA_ERROR);
    return false;
  }
  
  // 获取传感器并进行一些初始设置
  sensor_t *s = esp_camera_sensor_get();
  // 初始传感器垂直翻转，颜色有点饱和
  if (s->id.PID == OV3660_PID) {
    s->set_vflip(s, 1); // 翻转回来
    s->set_brightness(s, 1); // 稍微增加亮度
    s->set_saturation(s, -2); // 降低饱和度
  }
  
  // 为了更高的初始帧率，降低帧大小
  if(config.pixel_format == PIXFORMAT_JPEG){
    // s->set_framesize(s, FRAMESIZE_QVGA);
  }
  
#if defined(CAMERA_MODEL_ESP32S3_EYE)
  s->set_vflip(s, 1);
#endif
  
  _updateStatus(CAMERA_READY);
  return true;
}

// 开始定时获取图片帧
bool CameraManager::startCapture(FrameCallback callback, unsigned long intervalMs) {
  if (_status != CAMERA_READY) {
    Serial.println("Camera not ready, cannot start capture");
    return false;
  }
  
  _frameCallback = callback;
  _captureInterval = intervalMs;
  _lastCaptureTime = millis();
  _isCapturing = true;
  _updateStatus(CAMERA_RUNNING);
  
  return true;
}

// 停止定时获取图片帧
void CameraManager::stopCapture() {
  if (_isCapturing) {
    _isCapturing = false;
    _updateStatus(CAMERA_READY);
  }
}

// 销毁摄像头实例，释放所有资源
void CameraManager::destroy() {
  Serial.println("stopCapture");
  stopCapture();
  Serial.println("esp_camera_deinit");
  // 释放摄像头资源
  esp_camera_deinit();
  Serial.println("reset instance status");
  
  // 重置所有状态和回调
  _status = CAMERA_IDLE;
  _frameCallback = NULL;
  _statusCallback = NULL;
  _captureInterval = 0;
  _lastCaptureTime = 0;
  _isCapturing = false;
  
  Serial.println("Camera instance destroyed");
}

// 单独获取一帧图片
CameraFrame CameraManager::getFrame() {
  CameraFrame frame = {0};
  
  if (_status != CAMERA_READY && _status != CAMERA_RUNNING) {
    Serial.println("Camera not ready, cannot get frame");
    return frame;
  }
  
  // 从摄像头获取一帧
  camera_fb_t *fb = esp_camera_fb_get();
  if (!fb) {
    Serial.println("Camera capture failed");
    return frame;
  }
  
  // 填充帧信息
  frame.data = fb->buf;
  frame.size = fb->len;
  frame.fb = fb;
  
  return frame;
}

// 设置状态改变回调函数
void CameraManager::setStatusCallback(CameraStatusCallback callback) {
  _statusCallback = callback;
}

// 获取当前摄像头状态
CameraStatus CameraManager::getStatus() const {
  return _status;
}

// 释放帧资源
void CameraManager::releaseFrame(CameraFrame &frame) {
  if (frame.fb) {
    esp_camera_fb_return(frame.fb);
    frame.fb = NULL;
    frame.data = NULL;
    frame.size = 0;
  }
}

// 主循环处理函数
void CameraManager::loop() {
  // 检查是否需要进行帧捕获
  if (_isCapturing && _frameCallback) {
    unsigned long currentTime = millis();
    if (currentTime - _lastCaptureTime >= _captureInterval) {
      _lastCaptureTime = currentTime;
      _captureFrame();
    }
  }
}

// 更新摄像头状态
void CameraManager::_updateStatus(CameraStatus newStatus) {
  if (_status != newStatus) {
    _status = newStatus;
    if (_statusCallback) {
      _statusCallback(newStatus);
    }
    
    // 根据不同状态打印日志
    switch (newStatus) {
      case CAMERA_IDLE:
        Serial.println("Camera status: IDLE");
        break;
      case CAMERA_INITIALIZING:
        Serial.println("Camera status: INITIALIZING");
        break;
      case CAMERA_READY:
        Serial.println("Camera status: READY");
        break;
      case CAMERA_RUNNING:
        Serial.println("Camera status: RUNNING");
        break;
      case CAMERA_ERROR:
        Serial.println("Camera status: ERROR");
        break;
      default:
        break;
    }
  }
}

// 执行一次帧捕获
void CameraManager::_captureFrame() {
  if (_status != CAMERA_RUNNING || !_frameCallback) {
    return;
  }
  
  // 获取一帧图片
  CameraFrame frame = getFrame();
  if (frame.data && frame.size > 0) {
    // 调用回调函数传递帧
    _frameCallback(frame);
    
    // 释放帧资源
    releaseFrame(frame);
  }
}